import 'package:flut/src/config/pubspec_config.dart';
import 'package:flut/src/utils/utils.dart';
import 'package:path/path.dart';
import 'package:process_run/process_run.dart';

import '../config/config_exception.dart';
import '../utils/file_utils.dart';
import 'templates.dart';

/// The generator of initialization files.
class Initialization {
  late String projectName;

  /// Creates a new generator with configuration from the 'pubspec.yaml' file.
  Initialization() {
    final config = PubspecConfig();
    projectName = config.projectName;
  }

  /// Generates localization files.
  Future<void> generateAsync() async {
    await _generateProjectDirs();
    await _generateApis();
    await _generateConfigs();
    await _generateUtils();
    await _generateMainFile();
  }

  /// 项目依赖的通用插件集合
  Map<String, String> dependencyMap = {
    'dio':'  # 网络请求',
    'dio_http2_adapter':'  # 修改dio connect timeout解决设置连接超时时间无效而导致的网络慢的问题',
    'retrofit':'  # 网络接口包装工具',
    'json_annotation':'  # json相关注解',
    'get':'  # 状态管理',
    'get_storage':'  # 本地存储',
    'flutter_easyloading':'  # 提示框',
    'flutter_screenutil':'  # 屏幕适配',
    'cached_network_image':'  # 网络图片加载',
    'webview_flutter':'  # flutter中webview',
    'lottie':'  # lottie动画',
    'event_bus':'  # 事件总线 - 通知',
    'dev:json_serializable':'',
    'dev:build_runner':'',
    'dev:retrofit_generator':'',
  };

  String get dependenciesCmd  => dependencyMap.keys.join(" ");

  Future<void> runDependencies() async {
    await run('flutter pub add $dependenciesCmd');
    await _generatePubspecAnnotate();
  }

  Future<void> _generateProjectDirs() async {
    for (var value in [
      "apis/interceptor",
      "configs",
      "controllers",
      "entities",
      "ui/pages",
      "ui/widgets",
      "utils"
    ]) {
      await _generateProjectDir(value);
    }
  }

  Future<void> _generateMainFile() async {
    /// main.dart
    var outputDir = join('lib', 'main.dart');
    var content = generateMain(projectName);
    var formattedContent = formatDartContent(content, 'main.dart');
    await updateDartFile(formattedContent, outputDir);
  }

  Future<void> _generateApis() async {
    /// rest_client.dart
    var outputDir = join('lib', "apis", "rest_client.dart");
    var content = generateApiRestClient();
    var formattedContent = formatDartContent(content, 'rest_client.dart');
    await updateDartFile(formattedContent, outputDir);

    /// http.dart
    outputDir = join('lib', "apis", "http.dart");
    content = generateApiHttp();
    formattedContent = formatDartContent(content, 'http.dart');
    await updateDartFile(formattedContent, outputDir);

    /// api_exception.dart
    outputDir = join('lib', "apis", "api_exception.dart");
    content = generateApiException();
    formattedContent = formatDartContent(content, 'api_exception.dart');
    await updateDartFile(formattedContent, outputDir);

    /// interceptor.dart
    outputDir = join('lib', "apis", "interceptor", "interceptor.dart");
    content = generateApiInterceptor();
    formattedContent = formatDartContent(content, 'interceptor.dart');
    await updateDartFile(formattedContent, outputDir);

    /// header_interceptor.dart
    outputDir = join('lib', "apis", "interceptor", "header_interceptor.dart");
    content = generateApiHeaderInterceptor();
    formattedContent = formatDartContent(content, 'header_interceptor.dart');
    await updateDartFile(formattedContent, outputDir);

    /// api_result_interceptor.dart
    outputDir = join('lib', "apis", "interceptor", "api_result_interceptor.dart");
    content = generateApiResultInterceptor();
    formattedContent = formatDartContent(content, 'api_result_interceptor.dart');
    await updateDartFile(formattedContent, outputDir);
  }

  Future<void> _generateConfigs() async {
    /// colors.dart
    var outputDir = join('lib', "configs", "colors.dart");
    var content = generateColors();
    var formattedContent = formatDartContent(content, 'colors.dart');
    await updateDartFile(formattedContent, outputDir);

    /// themes.dart
    outputDir = join('lib', "configs", "themes.dart");
    content = generateThemes();
    formattedContent = formatDartContent(content, 'themes.dart');
    await updateDartFile(formattedContent, outputDir);

    /// app_tracking.dart
    outputDir = join('lib', "configs", "app_tracking.dart");
    content = generateTrackings();
    formattedContent = formatDartContent(content, 'app_tracking.dart');
    await updateDartFile(formattedContent, outputDir);
  }

  Future<void> _generateUtils() async {
    /// colors.dart
    var outputDir = join('lib', "utils", "colors.dart");
    var content = generateUtilsColors();
    var formattedContent = formatDartContent(content, 'colors.dart');
    await updateDartFile(formattedContent, outputDir);

    /// status_bar.dart
    outputDir = join('lib', "utils", "status_bar.dart");
    content = generateUtilsStatusBar();
    formattedContent = formatDartContent(content, 'status_bar.dart');
    await updateDartFile(formattedContent, outputDir);
  }

  Future<void> _generateProjectDir(String name) async {
    final configs = join('lib', name);
    var intlDir = getDirectory(configs);
    if (intlDir == null) {
      await createDirectory(configs);
    }
  }

  Future<void>  _generatePubspecAnnotate() async {
    var pubspecFile = getPubspecFile();
    if (pubspecFile == null) {
      throw ConfigException("Can't find 'pubspec.yaml' file.");
    }

    var pubspecFileLines = pubspecFile.readAsLinesSync();
    for (var key in dependencyMap.keys) {
      final value = dependencyMap[key]!;
      if (value.isNotEmpty) {
        int index = -1;
        for (int i = 0; i < pubspecFileLines.length; i++) {
          if (pubspecFileLines[i].contains(RegExp("$key:"))) {
            index = i;
          }
        }
        if (index != -1) {
          pubspecFileLines.insert(index, value);
        }
      }
    }

    /// 配置assets
    final assets = ['    - assets/images/','    - assets/lottie/'];
    int index = -1;
    for (int i = 0; i < pubspecFileLines.length; i++) {
      if (pubspecFileLines[i].contains(RegExp("# assets:"))) {
        index = i;
      }
    }
    if (index != -1) {
      pubspecFileLines[index] = '  assets:';
      int i = index + 1;
      int j = 0;
      while(pubspecFileLines[i].contains(RegExp("#   - images"))) {
        if (j < assets.length) {
          pubspecFileLines[i] = assets[j];
        } else {
          pubspecFileLines[i] = '';
        }
        i++;
        j++;
      }
    }

    // flutter_assert
    index = -1;
    for (int i = 0; i < pubspecFileLines.length; i++) {
      if (pubspecFileLines[i].contains(RegExp("flutter_assets_generator:"))) {
        index = i;
      }
    }
    if (index == -1) {
      pubspecFileLines.add(generatePubspecFlutterAssets());
    }

    await pubspecFile.writeAsString(pubspecFileLines.join('\n'));
  }
}
